#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

#include "cv.h"
#include "highgui.h"

#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/integral_image_normal.h>
#include <pcl/visualization/cloud_viewer.h>

#include <Eigen/Core> 
#include <Eigen/Geometry>

#include "g2o/core/graph_optimizer_sparse.h"
#include "g2o/core/hyper_graph.h"
#include "g2o/core/block_solver.h"
#include "g2o/core/solver.h"
#include "g2o/solvers/pcg/linear_solver_pcg.h"
#include "g2o/math_groups/se3quat.h"
#include "g2o/core/structure_only_solver.h"
#include "g2o/types/slam3d/vertex_se3_quat.h"
#include "g2o/types/slam3d/edge_se3_quat.h"
#include "graph/VertexCamera.cpp"
#include "graph/VertexPlane.cpp"
#include "graph/VertexPoint3D.cpp"
#include "graph/EdgeCameraPlane.cpp"

using namespace std;

struct Analyzation_data {
	int src_id;
	int dst_id;
	float val_time;
	float pos_error;
	float trans_error;
	float weight;
	Eigen::Matrix4f transformationMatrix;
	g2o::EdgeSE3 * g2oEdge;
};

struct Frame {
	int id;
	Eigen::Matrix4f matrix;
	g2o::VertexSE3 * g2oVertex;
};

int getdir (string dir, vector<string> &files)
{
    DIR *dp;
    struct dirent *dirp;
    if((dp  = opendir(dir.c_str())) == NULL) {
        cout << "Error(" << errno << ") opening " << dir << endl;
        return errno;
    }

    while ((dirp = readdir(dp)) != NULL) {
        files.push_back(string(dirp->d_name));
    }
    closedir(dp);
    return 0;
}


bool mycomparison (Analyzation_data * i,Analyzation_data * j) {
	if(i->src_id == j->src_id){	return i->dst_id < j->dst_id;}
	else{						return i->src_id < j->src_id;}
}

void analyzeTransformations(float max_thresh_rot,float max_thresh_pos,int thresh_steps, string dataset,vector< vector< vector<Analyzation_data * > * > * > * results,vector<Analyzation_data * > * gt_res){

	vector<Eigen::Matrix4f> gt_pos;
	Eigen::Matrix4f trmat = Eigen::Matrix4f::Identity();
	gt_pos.push_back(trmat);
	
	for(unsigned int nr = 0; nr < gt_res->size(); nr++)
	{
		Analyzation_data * data = gt_res->at(nr);
		trmat = trmat*data->transformationMatrix;
		gt_pos.push_back(trmat);
	}
	
	
	printf("%%---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
	for(int matcher = 0; matcher < results->size(); matcher++)
	{
		for(int step = 1; step < results->at(matcher)->size(); step++)
		{
			vector<Analyzation_data * > * current = results->at(matcher)->at(step);
			/*
			printf("%s_matcher%istep%ipos = [ ",dataset.c_str(),matcher,step);
			for(float thresh_counter = 1; thresh_counter <= thresh_steps; thresh_counter++)
			{
				float thresh = max_thresh_pos*float(thresh_counter)/float(thresh_steps);
				float nr_good = 0;
				float nr_bad = 0;
				for(int nr = 0; nr < current->size(); nr++)
				{
					Analyzation_data * data = current->at(nr);
					Eigen::Matrix4f mat = (gt_pos.at(data->dst_id).inverse() * gt_pos.at(data->src_id)).inverse() * data->transformationMatrix;
					float err = sqrt(mat(0,3)*mat(0,3)+mat(1,3)*mat(1,3)+mat(2,3)*mat(2,3));
					if(err < thresh){
						nr_good++;
					}else{
						nr_bad++;
					}
				}
				printf("%.3f ",float(nr_good)/float(nr_good+nr_bad));
			}
			
			printf("];\n");
			
			printf("%s_matcher%istep%irot = [ ",dataset.c_str(),matcher,step);
			
			for(float thresh_counter = 1; thresh_counter <= thresh_steps; thresh_counter++)
			{
				float thresh = max_thresh_rot*float(thresh_counter)/float(thresh_steps);
				float nr_good = 0;
				float nr_bad = 0;
				for(int nr = 0; nr < current->size(); nr++)
				{
					Analyzation_data * data = current->at(nr);
					Eigen::Matrix4f mat = (gt_pos.at(data->dst_id).inverse() * gt_pos.at(data->src_id)).inverse() * data->transformationMatrix;
					float trans_diff = 0;
					for(int q = 0; q < 4; q++){mat(q,q)-=1;}
					for(int q = 0; q < 3; q++)
					{
						for(int l = 0; l < 3; l++)
						{
							trans_diff+= fabs(mat(q,l));
						}
					}
					if(trans_diff < thresh){
						nr_good++;
					}else{
						nr_bad++;
					}
				}
				printf("%.3f ",float(nr_good)/float(nr_good+nr_bad));
			}
			
			printf("];\n");
			*/
			/*
			printf("%s_matcher%istep%iErrorRot=[",dataset.c_str(),matcher,step);
			for(int nr = 0; nr < current->size(); nr++)
			{
				Analyzation_data * data = current->at(nr);
				Eigen::Matrix4f mat = (gt_pos.at(data->dst_id).inverse() * gt_pos.at(data->src_id)).inverse() * data->transformationMatrix;
				float trans_diff = 0;
				for(int q = 0; q < 4; q++){mat(q,q)-=1;}
				for(int q = 0; q < 3; q++)
				{
					for(int l = 0; l < 3; l++)
					{
						trans_diff+= fabs(mat(q,l));
					}
				}
				printf(" %f",trans_diff);
			}
			printf("];\n");
			
			printf("%s_matcher%istep%iErrorPos=[",dataset.c_str(),matcher,step);
			for(int nr = 0; nr < current->size(); nr++)
			{
				Analyzation_data * data = current->at(nr);
				Eigen::Matrix4f mat = (gt_pos.at(data->dst_id).inverse() * gt_pos.at(data->src_id)).inverse() * data->transformationMatrix;
				float pos_diff = sqrt(mat(0,3)*mat(0,3)+mat(1,3)*mat(1,3)+mat(2,3)*mat(2,3));
				printf(" %f",pos_diff);
			}
			printf("];\n");
			*/
			
		}
		/*
		printf("%s_matcher%ipos = [ ",dataset.c_str(),matcher);
		for(int step = 1; step < results->at(matcher)->size(); step++)
		{
			vector<Analyzation_data * > * current = results->at(matcher)->at(step);
			float thresh = 0.02;
			float nr_good = 0;
			float nr_bad = 0;
			for(int nr = 0; nr < current->size(); nr++)
			{
				Analyzation_data * data = current->at(nr);
				Eigen::Matrix4f mat = (gt_pos.at(data->dst_id).inverse() * gt_pos.at(data->src_id)).inverse() * data->transformationMatrix;

				float pos_diff = sqrt(mat(0,3)*mat(0,3)+mat(1,3)*mat(1,3)+mat(2,3)*mat(2,3));
				float trans_diff = 0;
				for(int q = 0; q < 4; q++){mat(q,q)-=1;}
				for(int q = 0; q < 3; q++)
				{
					for(int l = 0; l < 3; l++)
					{
						trans_diff+= fabs(mat(q,l));
					}
				}
				//printf("src: %i dst: %i --> [%f %f]\n",data->src_id,data->dst_id,pos_diff,trans_diff);
				
				float err = pos_diff;
				if(err < thresh){
					nr_good++;
				}else{
					nr_bad++;
				}
			}
			printf("%.3f ",float(nr_good)/float(nr_good+nr_bad));
		}
		printf("];\n");
		
		printf("%s_matcher%irot = [ ",dataset.c_str(),matcher);
		for(int step = 1; step < results->at(matcher)->size(); step++)
		{
			vector<Analyzation_data * > * current = results->at(matcher)->at(step);
			float thresh = 0.05;
			float nr_good = 0;
			float nr_bad = 0;
			for(int nr = 0; nr < current->size(); nr++)
			{
				Analyzation_data * data = current->at(nr);
				Eigen::Matrix4f mat = (gt_pos.at(data->dst_id).inverse() * gt_pos.at(data->src_id)).inverse() * data->transformationMatrix;

				float pos_diff = sqrt(mat(0,3)*mat(0,3)+mat(1,3)*mat(1,3)+mat(2,3)*mat(2,3));
				float trans_diff = 0;
				for(int q = 0; q < 4; q++){mat(q,q)-=1;}
				for(int q = 0; q < 3; q++)
				{
					for(int l = 0; l < 3; l++)
					{
						trans_diff+= fabs(mat(q,l));
					}
				}
				//printf("src: %i dst: %i --> [%f %f]\n",data->src_id,data->dst_id,pos_diff,trans_diff);
				
				float err = trans_diff;
				if(err < thresh){
					nr_good++;
				}else{
					nr_bad++;
				}
			}
			printf("%.3f ",float(nr_good)/float(nr_good+nr_bad));
		}
		printf("];\n");
		*/
		float tot_time = 0.0;
		float tot = 0;
		for(int step = 1; step < results->at(matcher)->size(); step++)
		{
			vector<Analyzation_data * > * current = results->at(matcher)->at(step);
			
			for(int nr = 0; nr < current->size(); nr++)
			{
				Analyzation_data * data = current->at(nr);
				tot_time+=data->val_time;
				tot++;
			}
			//printf("%.5f ",tot_time/float(current->size()));
		}
		
		printf("%s_matcher%itime = %.5f;\n",dataset.c_str(),matcher,tot_time/tot);
		//printf("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
	}
}

int main(int argc, char **argv)
{
	//string out_path = "output/";
	string out_path = "output_AICK/";
	//string out_path = "/media/2A98195B9819273B/output_ssd/output/output/";
	vector<string> datasets = vector<string>();

	//datasets.push_back("KeyPointIcpStrongv2");
	//datasets.push_back("KeyPointIcpStrongv2calb1");
	//datasets.push_back("calib0test");
	//datasets.push_back("calib1test");
	//datasets.push_back("BasicGIcpMatcher");
	//datasets.push_back("KeyPointIcpStrongv2");
	//datasets.push_back("kpICP2");
	//datasets.push_back("kpICP1");
	//datasets.push_back("NrKPs");
	//datasets.push_back("NrIter");
	//datasets.push_back("AICK1");
	//datasets.push_back("AICK2");
	//datasets.push_back("AICKFULL");
	datasets.push_back("AICKFULLv2");

	//datasets.push_back("kpICP2");
	vector<string> files = vector<string>();
	getdir(out_path,files);
	printf("nr files: %i\n",files.size());
	printf("%s\n",out_path.c_str());
	vector< vector< vector< vector<Analyzation_data * > * > * > * > * all_results = new vector< vector<vector<vector<Analyzation_data * > * > * > * >();
	for(unsigned int d = 0; d < datasets.size(); d++){
		string prefix = datasets.at(d);
		vector< vector< vector<Analyzation_data * > * > * > * results = new vector<vector<vector<Analyzation_data * > * > * >();
		all_results->push_back(results);
		for (unsigned int i = 0;i < files.size();i++) {
			if(files.at(i).find(prefix)==0 && files.at(i).find("_") == prefix.length()){
				if(i%1000 == 0){printf("%i:%s\n",i,files.at(i).c_str());}
			
				ifstream task_file ((out_path+files.at(i)).c_str());
				if (task_file.is_open()){
					task_file.seekg(0,ifstream::end);
					long size =task_file.tellg();
					if(size == 0){printf("size == 0\n");task_file.close();}
					else{
						char * buffer_char 		= new char [size];
						int * buffer_int 		= (int *) buffer_char;
						float * buffer_float	= (float *) buffer_char;
						task_file.seekg(0);
						task_file.read (buffer_char,size);
						task_file.close();

						int step 			= buffer_int[0] - buffer_int[1];
						int matcher_id		= buffer_int[2];
						while(results->size() <= matcher_id){results->push_back(new vector<vector<Analyzation_data * > * >());}
						while(results->at(matcher_id)->size() <= step){results->at(matcher_id)->push_back(new vector<Analyzation_data * >());}
						if(buffer_int[3] == 1){
							Analyzation_data * data = new Analyzation_data();
							data->src_id 			= buffer_int[0];
							data->dst_id 			= buffer_int[1];
					
							data->val_time 			= buffer_float[4];
							data->pos_error 		= buffer_float[5];
							data->trans_error 		= buffer_float[6];
							data->weight 			= buffer_float[7];
							data->transformationMatrix(0,0) = buffer_float[8 ];
						 	data->transformationMatrix(0,1) = buffer_float[9 ];
							data->transformationMatrix(0,2) = buffer_float[10];
							data->transformationMatrix(0,3) = buffer_float[11];
							data->transformationMatrix(1,0) = buffer_float[12];
							data->transformationMatrix(1,1) = buffer_float[13];
							data->transformationMatrix(1,2) = buffer_float[14];
							data->transformationMatrix(1,3) = buffer_float[15];
							data->transformationMatrix(2,0) = buffer_float[16];
							data->transformationMatrix(2,1) = buffer_float[17];
							data->transformationMatrix(2,2) = buffer_float[18];
							data->transformationMatrix(2,3) = buffer_float[19];
							data->transformationMatrix(3,0) = buffer_float[20];
							data->transformationMatrix(3,1) = buffer_float[21];
							data->transformationMatrix(3,2) = buffer_float[22];
							data->transformationMatrix(3,3) = buffer_float[23];
							results->at(matcher_id)->at(step)->push_back(data);
						}else{printf("not calculated\n");}
						delete buffer_char;
					}
		    	}else{
		    		printf("failed to open file\n");
		    	}
		    } 
		}
    }
    vector<Analyzation_data * > * gt_res = new vector<Analyzation_data * >();
	for (unsigned int i = 0;i < files.size();i++) {
		if(files.at(i).find("groundtrouth")==0){
			ifstream task_file ((out_path+files.at(i)).c_str());
			if (task_file.is_open()){
				task_file.seekg(0,ifstream::end);
				long size				=task_file.tellg();
				char * buffer_char 		= new char [size];
				int * buffer_int 		= (int *) buffer_char;
				float * buffer_float	= (float *) buffer_char;
				task_file.seekg(0);
				task_file.read (buffer_char,size);
				task_file.close();
				
				if(buffer_int[3] == 1){
					Analyzation_data * data = new Analyzation_data();
					data->src_id 					= buffer_int[0];
					data->dst_id 					= buffer_int[1];
					
					data->val_time 					= buffer_float[4 ];
					data->pos_error 				= buffer_float[5 ];
					data->trans_error 				= buffer_float[6 ];
					data->weight 					= buffer_float[7 ];
					data->transformationMatrix(0,0) = buffer_float[8 ];
				 	data->transformationMatrix(0,1) = buffer_float[9 ];
					data->transformationMatrix(0,2) = buffer_float[10];
					data->transformationMatrix(0,3) = buffer_float[11];
					data->transformationMatrix(1,0) = buffer_float[12];
					data->transformationMatrix(1,1) = buffer_float[13];
					data->transformationMatrix(1,2) = buffer_float[14];
					data->transformationMatrix(1,3) = buffer_float[15];
					data->transformationMatrix(2,0) = buffer_float[16];
					data->transformationMatrix(2,1) = buffer_float[17];
					data->transformationMatrix(2,2) = buffer_float[18];
					data->transformationMatrix(2,3) = buffer_float[19];
					data->transformationMatrix(3,0) = buffer_float[20];
					data->transformationMatrix(3,1) = buffer_float[21];
					data->transformationMatrix(3,2) = buffer_float[22];
					data->transformationMatrix(3,3) = buffer_float[23];
					gt_res->push_back(data);
				}
				delete buffer_char;
        	}else{
        		printf("failed to open file\n");
        	}
        } 
    }
	sort(gt_res->begin(),gt_res->end(),mycomparison);
	
	vector<Eigen::Matrix4f> gt_pos;
	Eigen::Matrix4f trmat = Eigen::Matrix4f::Identity();
	gt_pos.push_back(trmat);
	
	for(unsigned int nr = 0; nr < gt_res->size(); nr++)
	{
		Analyzation_data * data = gt_res->at(nr);
		trmat = trmat*data->transformationMatrix;
		gt_pos.push_back(trmat);
	}
	/*
	printf("GT_x = [");
	for(unsigned int nr = 0; nr < gt_pos.size(); nr++)
	{
		Eigen::Matrix4f t = gt_pos.at(nr);
		printf(" %f",t(0,3));
	}
	printf("];\n");
	
	printf("GT_y = [");
	for(unsigned int nr = 0; nr < gt_pos.size(); nr++)
	{
		Eigen::Matrix4f t = gt_pos.at(nr);
		printf(" %f",t(1,3));
	}
	printf("];\n");
	
	printf("GT_z = [");
	for(unsigned int nr = 0; nr < gt_pos.size(); nr++)
	{
		Eigen::Matrix4f t = gt_pos.at(nr);
		printf(" %f",t(2,3));
	}
	printf("];\n");
	
	float tot_dist = 0;
	for(int i = 0; i < gt_res->size(); i++){
		Analyzation_data * data = gt_res->at(i);
		tot_dist+=sqrt(data->transformationMatrix(0,3)*data->transformationMatrix(0,3)+data->transformationMatrix(1,3)*data->transformationMatrix(1,3)+data->transformationMatrix(2,3)*data->transformationMatrix(2,3));
		//printf("%i: %f\n",i,tot_dist);
	}
	for(unsigned int d = 0; d < datasets.size(); d++){
		string prefix = datasets.at(d);
		printf("%%Dataset: %s\n",prefix.c_str());
		for(int matcher = 0; matcher < all_results->at(d)->size(); matcher++)
		{
			vector<Analyzation_data * > * current = all_results->at(d)->at(matcher)->at(1);
			sort(current->begin(),current->end(),mycomparison);
			
			vector<Eigen::Matrix4f> matcher_0_0_pos;
			vector<Eigen::Matrix4f> matcher_1_0_pos;
			vector<Eigen::Matrix4f> matcher_0_1_pos;
			Eigen::Matrix4f matcher_0_0_trmat = Eigen::Matrix4f::Identity();
			Eigen::Matrix4f matcher_1_0_trmat = Eigen::Matrix4f::Identity();
			Eigen::Matrix4f matcher_0_1_trmat = Eigen::Matrix4f::Identity();
			matcher_0_0_pos.push_back(matcher_0_0_trmat);
			matcher_1_0_pos.push_back(matcher_1_0_trmat);
			matcher_0_1_pos.push_back(matcher_0_1_trmat);
			for(unsigned int nr = 0; nr < current->size(); nr++)
			{
				Analyzation_data * data = current->at(nr);
				Eigen::Matrix4f c_0_0 = data->transformationMatrix;
				Eigen::Matrix4f c_1_0 = data->transformationMatrix;//FIXX
				Eigen::Matrix4f c_0_1 = data->transformationMatrix;//FIXX
				
				Analyzation_data * true_data = gt_res->at(nr);
				c_0_1(0,3) = true_data->transformationMatrix(0,3);
				c_0_1(1,3) = true_data->transformationMatrix(1,3);
				c_0_1(2,3) = true_data->transformationMatrix(2,3);
				

				c_1_0(0,0) = true_data->transformationMatrix(0,0);
				c_1_0(0,1) = true_data->transformationMatrix(0,1);
				c_1_0(0,2) = true_data->transformationMatrix(0,2);
					
				c_1_0(1,0) = true_data->transformationMatrix(1,0);
				c_1_0(1,1) = true_data->transformationMatrix(1,1);
				c_1_0(1,2) = true_data->transformationMatrix(1,2);
					
				c_1_0(2,0) = true_data->transformationMatrix(2,0);
				c_1_0(2,1) = true_data->transformationMatrix(2,1);
				c_1_0(2,2) = true_data->transformationMatrix(2,2);
					
				c_1_0(3,0) = true_data->transformationMatrix(3,0);
				c_1_0(3,1) = true_data->transformationMatrix(3,1);
				c_1_0(3,2) = true_data->transformationMatrix(3,2);
				c_1_0(3,3) = true_data->transformationMatrix(3,3);
				
				matcher_0_0_trmat = matcher_0_0_trmat*c_0_0;
				matcher_1_0_trmat = matcher_1_0_trmat*c_1_0;
				matcher_0_1_trmat = matcher_0_1_trmat*c_0_1;
				matcher_0_0_pos.push_back(matcher_0_0_trmat);
				matcher_1_0_pos.push_back(matcher_1_0_trmat);
				matcher_0_1_pos.push_back(matcher_0_1_trmat);
			}
			
			printf("%s_matcher%i_x_0_0 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_0_0_pos.at(nr))(0,3));}
			printf("];\n");
				
			printf("%s_matcher%i_y_0_0 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_0_0_pos.at(nr))(1,3));}
			printf("];\n");
				
			printf("%s_matcher%i_z_0_0 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_0_0_pos.at(nr))(2,3));}
			printf("];\n");
				
			printf("%s_matcher%i_x_1_0 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_1_0_pos.at(nr))(0,3));}
			printf("];\n");
				
			printf("%s_matcher%i_y_1_0 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_1_0_pos.at(nr))(1,3));}
			printf("];\n");
				
			printf("%s_matcher%i_z_1_0 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_1_0_pos.at(nr))(2,3));}
			printf("];\n");

			printf("%s_matcher%i_x_0_1 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_0_1_pos.at(nr))(0,3));}
			printf("];\n");
				
			printf("%s_matcher%i_y_0_1 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_0_1_pos.at(nr))(1,3));}
			printf("];\n");
				
			printf("%s_matcher%i_z_0_1 = [ 0",datasets.at(d).c_str(),matcher);
			for(int nr = 1; nr <= current->size(); nr++){printf(" %f",(matcher_0_1_pos.at(nr))(2,3));}
			printf("];\n");
		}
	}
	//exit(0);
	
	printf("                                                ==================                        \n");
	printf("                                          ==============================                  \n");
	printf("                                    ==========================================            \n");
	printf("                              ======================================================      \n");
	printf("                        ==================================================================\n");
	printf("                  ==============================================================================\n");
	printf("            ==========================================================================================\n");
	printf("      ======================================================================================================\n");
	printf("==================================================================================================================\n");
	*/
	float max_thresh_rot = 0.25;
	float max_thresh_pos = 0.1;
	int thresh_steps = 50;
	printf("threshold_rot = [ ");
	for(float thresh_counter = 1; thresh_counter <= thresh_steps; thresh_counter++)
	{
		float thresh = max_thresh_rot*float(thresh_counter)/float(thresh_steps);
		printf("%.3f ",thresh);
	}
	printf("];\n");
	
	printf("threshold_pos = [ ");
	for(float thresh_counter = 1; thresh_counter <= thresh_steps; thresh_counter++)
	{
		float thresh = max_thresh_pos*float(thresh_counter)/float(thresh_steps);
		printf("%.3f ",thresh);
	}
	printf("];\n");
	for(unsigned int d = 0; d < datasets.size(); d++){
		string prefix = datasets.at(d);
		printf("%%Dataset: %s\n",prefix.c_str());
		printf("==============================================================================================================================\n");
		analyzeTransformations(max_thresh_rot,max_thresh_pos,thresh_steps,prefix,all_results->at(d),gt_res);
	}
	exit(0);
	/*
	printf("==================================================================================================================\n");
	printf("      ======================================================================================================\n");
	printf("            ==========================================================================================\n");
	printf("                  ==============================================================================\n");
	printf("                        ==================================================================\n");
	printf("                              ======================================================      \n");
	printf("                                    ==========================================            \n");
	printf("                                          ==============================                  \n");
	printf("                                                ==================                        \n");
	*/

	

	return 0;
}



